package B2dsc::Controller::Faidx;

# by lhtk : lhtk80t7@gmail.com
use Mojo::Base ('Mojolicious::Controller', 'Exporter');
use File::Basename;
use Bio::SeqIO;
# use JSON qw/to_json/;
use ShareSubs qw/get_conf init_conf_file/;
use autodie qw/open close/;

# use Mojo::Base 'Exporter';
# 此函数暂时并没有被使用
our @EXPORT_OK = qw/fecth_seq/;

# -----------------------------------------------
my $conf_dir = 'conf/faidx';
my %available_dbs;
get_available_dbs();
# our $conf = get_conf('faidx.json');

sub index {
	my $self = shift;
	return $self->render(available_dbs => [ sort keys %available_dbs ]);
}

sub handle_ajax {
	my $self = shift;

	# # 返回一个数组吧
	# my $json_data;

	# Check if parameters have been submitted
	my $validation = $self->validation;

	# 必须包含 species, chrName, start, end
	# strand 可选
	$validation->required('species')->in(keys %available_dbs);
	$validation->required('chrName')->like(qr/^\w+$/);

	my $species = $self->param('species');
	# return $self->render(json => {}) unless (exists $conf->{$species});
	return $self->render(json => {}) unless (exists $available_dbs{$species});
	my $conf = get_conf(join '/', $conf_dir, "$species.json");

	# 返回 chrName 信息
	if ($validation->has_error) {
		return $self->render(json => $conf->{chromosome});
	}

	for my $i ('start', 'end') {
		$validation->required($i)->like(qr/^\d+$/);
	}
	return $self->render(json => {}) if $validation->has_error;

	my $chrName = $self->param('chrName');

	# start 必须小于 end
	my $start = $self->param('start');
	my $end = $self->param('end');
	return $self->render(json => {}) unless ($start > 0 and $start <= $end);
	my $strand = $self->param('strand'); # 1, -1

	my $seq_ref = fecth_seq({
		species => $species,
		chrName => $chrName,
		start   => $start,
		end     => $end,
		strand  => $strand,
	});
	# $json_data->{seq} = $o_str;
	# $json_data->{seq} = $$seq_ref;

	return $self->render(json => {seq => $$seq_ref});
}

sub fecth_seq {
	my $params = shift;
	my($species,$chrName,$start,$end,$strand) = @{$params}{qw/species chrName start end strand/};
	my $conf = get_conf(join '/', $conf_dir, "$species.json");

	my($hgrp, $genome) = ($chrName =~ /^(\d+)(\w+)$/);
	# my $fa = join('/', $conf->{$species}{dir}, $conf->{$species}{chromosome}{$genome}{$hgrp}[0]);
	# my $ssid = $conf->{$species}{chromosome}{$genome}{$hgrp}[1];
	# my $chrLen = $conf->{$species}{chromosome}{$genome}{$hgrp}[2];
	my $fa = join('/', $conf->{dir}, $conf->{chromosome}{$genome}{$hgrp}[0]);
	my $ssid = $conf->{chromosome}{$genome}{$hgrp}[1];
	my $chrLen = $conf->{chromosome}{$genome}{$hgrp}[2];
	my $desc = "$chrName; chromosome length: $chrLen bp";

	return \">$ssid:$start-$end $desc; Out of range!!!\n" if $start > $chrLen;
	
	$end = $chrLen if $end > $chrLen;

	my $r = `samtools faidx $fa $ssid:$start-$end`;

	# $json_data->{seq} = `samtools faidx $fa $ssid:$start-$end`;
	open my ($str_fh), '<', \$r;
	my $o_str;
	open my ($str_o_fh), '>', \$o_str;
	my $stream = Bio::SeqIO->newFh(-format => 'Fasta', -fh => $str_fh);
	my $stream_o = Bio::SeqIO->newFh(-format => 'Fasta', -fh => $str_o_fh);
	while (my $seq = <$stream>) {
		return \$r if ($seq->length < 1);
		if ($strand == -1) {
			my $rev = $seq->revcom();
			# $desc .= '; ' . 'Here is the reverse complement sequence.';
			$desc .= '; ' . 'reverse complement: true';
			$rev->desc($desc);
			$rev->seq( uc($rev->seq()) );
			print $stream_o $rev;
		} else {
			$seq->desc($desc);
			$seq->seq( uc($seq->seq()) );
			print $stream_o $seq;
		}
	}
	close $str_fh;
	close $str_o_fh;

	return \$o_str;
}

sub get_available_dbs {
	my @conf_files = <$conf_dir/*.json>;
    # 如果一个配置文件都没有，初始化一下
    init_conf_file("$conf_dir/example.json") unless @conf_files;
	for my $f (@conf_files) {
		my $bname = basename($f, '.json');
		$available_dbs{$bname} = 1;
	}
}

# -----------------------------------------------
1;